#ifndef _EVENT_HANDLER_H
#define _EVENT_HANDLER_H

namespace NetIO
{
struct Operation;
typedef TAILQ_HEAD( _operations, Operation ) Operations;

class Operation_Queue
{
public:
	Operations	*operations_;

	Operation_Queue( );

	~Operation_Queue( );

	Operation *front( );

	void pop( );

	void push( Operation *op );

	bool empty( );

	void concat( Operation_Queue *op_queue );
};

class Handle_Data
{
public:
	Handle_Data( void )
		: is_cancel_( false )
	{
	}
public:
	~Handle_Data( void )
	{

	}
	static Handle_Data *make()
	{
		return new Handle_Data( );
	}

	void destroy( )
	{
		delete this;
	}
public:
	Operation_Queue	operations_[ OperationType::CONNECT ];
	Synch_Mutex		mutex_;
	bool			is_cancel_;
};

class DllExport Socket
{
	friend class Reactor_Impl;
	friend class Select_Reactor;
	friend class Epoll_Reactor;
	friend struct Operation;
public:
	Socket( )
		: handle_( INVALID_HANDLE )
		, handle_data_( 0 )
	{
	}

	operator const EventHandle& ( ) const
	{
		return handle_;
	}

	void close( );

	void open( )
	{
		if ( is_open( ) )
			return;

		handle_ = socket (AF_INET, SOCK_STREAM, 0);
	}

	bool is_open( )  const
	{
		return handle_ != INVALID_HANDLE;
	}

	void remoteaddr( string &ip, short &port ) const
	{
		sockaddr_in addr = {0};
		int len = sizeof( addr );
		getpeername( handle_, (sockaddr*)&addr, &len );
		ip = inet_ntoa( addr.sin_addr );
		port = ntohs( addr.sin_port );
	}

	void localaddr( string &ip, short &port ) const
	{
		sockaddr_in addr = {0};
		int len = sizeof( addr );
		getsockname( handle_, (sockaddr*)&addr, &len );
		ip = inet_ntoa( addr.sin_addr );
		port = ntohs( addr.sin_port );
	}

private:
	EventHandle handle( )
	{
		return handle_;
	}
	 
	void handle( EventHandle handle )
	{
		handle_ = handle;
	}
	
	Handle_Data *handle_data( ) const
	{
		return handle_data_;
	}
	
	void handle_data( Handle_Data *data )
	{
		handle_data_ = data;
	}
	
	EventHandle & operator( )( )
	{
		return handle_;
	}

private:
	EventHandle	handle_;

	Handle_Data	*handle_data_;

};

}
#endif